package think.in.java.concurrency.practise.exec6;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by IntelliJ IDEA.
 * User: Richard
 * Date: 5/19/11
 * Time: 9:00 PM
 * use the lock for the sync , note , the tryLock will get the lock when it available
 * the lock method will waiting for the lock release , so the lock method will schedule by the jvm
 * and you can operate the lock by using the tryLock method , so may be in a high sync enviroment , there will
 * be less thread waiting for the release-lock.
 */
public class EvenGeneratorForLock extends IntGenerate {
    //use the   AtomicInteger for the sync
    private int currentValue = 0;
    private ReentrantLock lock = new ReentrantLock();


    @Override
    //this class can't be fix by using the volatile , as there will be many method access this method ,
    //but the increase number will be less , as we use the volatile for the int
    //and if we use AtomicInteger the increase will less more
    //note don't use the tryLock and lock method together , then it will lock twice
    public int next() {
        boolean captured = false;
        try {
            // the trylock will try the lock , if the lock is available , the is will lock current thread
            //and we can use the time out optional for how long the try process will take
            captured = lock.tryLock(1,TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        try {
            while (!captured) {
                // System.out.println("======waiting-captured=====");
                Thread.yield();
                captured = lock.tryLock(1, TimeUnit.SECONDS);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        if (captured) {
            try {
                //note , don't use the try lock and lock together , and the lock method will lock the
                //thread manually
                //and use the lock , current thread will waiting the lock to be release
                //If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes
                // and lies dormant until the lock has been acquired, at which time the lock hold count is set to one.
                //lock.lock();
                currentValue++;
                currentValue++;
                return currentValue;
            } finally {
                lock.unlock();

            }
        } else {
            return currentValue;
        }
    }

}
